package no.sachmuld.methodcombination.api;

import junit.framework.Assert;
import org.junit.Test;

/**
 *
 */
public abstract class ExceptionPropagationTestTemplate {

    @Test
    public void shouldPropagateCheckedException() throws Exception {

        Foo foo = createFoo();
        foo.with(new FooBehaviour() {
            @Override
            public void checkedBar(MethodInvocation<Void> methodInvocation) throws FooCheckedException {
                throw new FooCheckedException();
            }
        });
        foo.with(new FooBehaviour() {
            @Override
            public void checkedBar(MethodInvocation<Void> methodInvocation) {
                methodInvocation.proceed();
            }
        });

        boolean exception = false;

        try {
            foo.checkedBar();
        } catch (FooCheckedException e) {
            exception = true;
        }

        Assert.assertTrue(exception);

    }

    @Test
    public void shouldPropagateRuntimeException() throws Exception {

        Foo foo = createFoo();
        foo.with(new FooBehaviour() {
            @Override
            public void runtimeBar(MethodInvocation<Void> methodInvocation) throws FooRuntimeException {
                throw new FooRuntimeException();
            }
        });
        foo.with(new FooBehaviour() {
            @Override
            public void runtimeBar(MethodInvocation<Void> methodInvocation) {
                methodInvocation.proceed();
            }
        });

        boolean exception = false;

        try {
            foo.runtimeBar();
        } catch (FooRuntimeException e) {
            exception = true;
        }

        Assert.assertTrue(exception);

    }

    public static class FooCheckedException extends Exception {};
    public static class FooRuntimeException extends RuntimeException {};

    static public abstract class FooBehaviour {
        public void checkedBar(MethodInvocation<Void> methodInvocation) throws FooCheckedException {
            methodInvocation.proceed();
        }

        public void runtimeBar(MethodInvocation<Void> methodInvocation) throws FooRuntimeException {
            methodInvocation.proceed();
        }
    }

    static public abstract class Foo extends MethodCombinationSupport<FooBehaviour> {
        public abstract void checkedBar() throws FooCheckedException;
        public abstract void runtimeBar() throws FooRuntimeException;

    }

    protected abstract Foo createFoo();

}
